package com.ego.geteway.config;

import com.ego.auth.utils.JwtUtils;
import com.ego.geteway.properties.AuthProperties;
import com.ego.geteway.properties.JwtProperties;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpCookie;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.MultiValueMap;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import javax.annotation.Resource;

/**
 * 〈〉
 *
 * @author coach tam
 * @email 327395128@qq.com
 * @create 2021/4/15
 * @since 1.0.0
 * 〈坚持灵活 灵活坚持〉
 */
@Slf4j
@EnableConfigurationProperties({AuthProperties.class, JwtProperties.class})
@Component
public class AuthFilter implements GlobalFilter, Ordered {

    @Resource
    private AuthProperties authProperties;
    @Resource
    private JwtProperties jwtProperties;

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {

        //判断当前请求路径是否白名单
        ServerHttpRequest request = exchange.getRequest();
        ServerHttpResponse response = exchange.getResponse();
        //    /api/auth/login
        String path = request.getURI().getPath();

        boolean match = authProperties.getAllowUrlList().stream()
                //只要当前请求路径以某个前缀开头，返回true，表示当前访问得是白名单，所以放行
                .anyMatch(url -> path.startsWith(url));
        //1.是->放行
        if (match) {
            return chain.filter(exchange);
        }
        else {
            try {
                //2.不是->通过公钥校验token是否有效
                //2.1.从cookie中获取token
                MultiValueMap<String, HttpCookie> cookies = request.getCookies();
                String token = cookies.getFirst(jwtProperties.getCookieName()).getValue();
                //2.2.通过公钥校验token
                JwtUtils.getInfoFromToken(token, jwtProperties.getPublicKey());
                //2.2.1.通过->放行
                return chain.filter(exchange);
            } catch (Exception e) {
                //2.2.2.不通过->返回401
                log.error("未授权，请先获取token",e);
                response.setStatusCode(HttpStatus.UNAUTHORIZED);
                return response.setComplete();
            }
        }
    }

    @Override
    public int getOrder() {
        return 0;
    }


}
